﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Processors;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;


namespace XMasContent
{
    class XmasContent
    {
        private static XmasContent m_Instance = null;
        ContentProcessorContext _contextProcessor;
        ContentImporterContext  _contextImporter;


        public static XmasContent GetInstance()
        {
            if (m_Instance == null)
                m_Instance = new XmasContent();

            return m_Instance;
        }

        # region Load Utils

        public Vector2 readVector2(BinaryReader reader)
        {
            Vector2 v;
            v.X = reader.ReadSingle();
            v.Y = reader.ReadSingle();
            return v;
        }

        public Vector3 readVector3(BinaryReader reader)
        {
            Vector3 v;
            v.X = reader.ReadSingle();
            v.Y = reader.ReadSingle();
            v.Z = reader.ReadSingle();
            return v;
        }

        public Quaternion readQuaternion(BinaryReader reader)
        {
            Quaternion v;
            v.X = reader.ReadSingle();
            v.Y = reader.ReadSingle();
            v.Z = reader.ReadSingle();
            v.W = reader.ReadSingle();
            return v;
        }

        public string readString(BinaryReader reader)
        {
            string sResult = "";
            int nbytes;
            nbytes = reader.ReadInt32();
            char[] str = new char[nbytes];
            str = reader.ReadChars(nbytes);
            for (int i = 0; i < nbytes - 2; ++i)
                sResult = sResult + str[i];
            return sResult;
        }

        #endregion


        #region Warn and Context

        public void SetContextProcessor(ContentProcessorContext context)
        {
            _contextProcessor = context;
            _contextImporter  = null;
        }

        public void SetContextImporter(ContentImporterContext context)
        {
            _contextImporter  = context;
            _contextProcessor = null;
        }

        public void warn(string error_message, bool bWarning)
        {
            ContentBuildLogger logger = null;

            if (_contextImporter != null)
                logger = _contextImporter.Logger;
            else if (_contextProcessor != null)
                logger = _contextProcessor.Logger;

            if (logger != null)
            {
                if (bWarning)
                    logger.LogWarning(null, null, error_message);
                else
                    logger.LogMessage(error_message);
            }
        }

        #endregion


        #region Material

        public MaterialContent GetSkinningMaterial(string directory, MaterialContent material, ContentProcessorContext context)
        {
            string d = directory.ToLower();
            if (d.IndexOf("content") > 0)
            {
                int pos = d.IndexOf("content");
                d = d.Substring(0, pos) + "content";
            }

            EffectMaterialContent effectMaterial = new EffectMaterialContent();
            effectMaterial.Effect = new ExternalReference<EffectContent>
                (Path.Combine(d, "SkinnedModel.fx"));

            // copy the textures in the original material to the new normal mapping
            // material. this way the diffuse texture is preserved. The
            // PreprocessSceneHierarchy function has already added the normal map
            // texture to the Textures collection, so that will be copied as well.
            foreach (KeyValuePair<String, ExternalReference<TextureContent>> texture
                in material.Textures)
            {
                effectMaterial.Textures.Add(texture.Key, texture.Value);
            }

            // and convert the material using the NormalMappingMaterialProcessor,
            // who has something special in store for the normal map.
            return context.Convert<MaterialContent, MaterialContent>
                (effectMaterial, typeof(MaterialProcessor).Name);
        }

    #endregion

    }

}